﻿namespace NJQuery {
	using System;
	using System.Web.UI;
	using System.Web.UI.WebControls;
	using System.ComponentModel;

	/// <summary>
	/// Base class used by widgets to provide a set of child controls as contained panels.
	/// </summary>
	[ParseChildren(true), PersistChildren(false)]
	public abstract class ChildPanel : WebControl, IGroupContainedControl {


		#region Fields

		private GroupControlContainer container;
		private ITemplate content;
		private GroupControlContainer contentContainer;

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="ChildPanel"/> object.
		/// </summary>
		/// <param name="tag">One of the <see cref="HtmlTextWriterTag"/> values.</param>
		protected ChildPanel(HtmlTextWriterTag tag) : base(tag) { }

		#endregion


		#region Properties: Grouped Child Controls

		/// <summary>
		/// Gets a <see cref="ControlCollection"/> object that represents the child controls for a specified server control in the UI hierarchy.
		/// </summary>
		public override sealed ControlCollection Controls {
			get { return base.Controls; }
		}

		/// <summary>
		/// Gets a <see cref="GroupedControlCollection"/> object that represents the grouped child controls for a server control in the UI hierarcy.
		/// </summary>
		protected virtual GroupedControlCollection GroupedControls {
			get { return (GroupedControlCollection)base.Controls; }
		}

		#endregion


		#region Properties: Templates

		/// <summary>
		/// Gets or sets the template that defines the content of the <see cref="Dialog"/> control.
		/// </summary>
		[TemplateInstance(TemplateInstance.Single), PersistenceMode(PersistenceMode.InnerProperty), Browsable(false)]
		public ITemplate Content {
			get { return content; }
			set { content = value; }
		}

		/// <summary>
		/// Gets a control object to which you can programmatically add child controls for <see cref="Content"/>.
		/// </summary>
		[Browsable(false)]
		public Control ContentContainer {
			get {
				EnsureChildControls();
				return contentContainer;
			}
		}

		#endregion


		#region Properties: Protected

		/// <summary>
		/// Gets or sets the control containing the control.
		/// </summary>
		protected virtual GroupControlContainer Container {
			get { return container; }
			set { container = value; }
		}

		#endregion


		#region Methods: Grouped child controls

		/// <summary>
		/// Returns the collection of all controls that are contained in the <see cref="Dialog"/> control.
		/// </summary>
		/// <returns>A <see cref="ControlCollection"/> object that consists of all controls that define the content of the <see cref="Dialog"/> control.</returns>
		protected override sealed ControlCollection CreateControlCollection() {
			return new GroupedControlCollection(this);
		}

		#endregion


		#region Methods: Child controls

		/// <summary>
		/// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
		/// </summary>
		protected override void CreateChildControls() {
			base.CreateChildControls();

			if(contentContainer == null) {
				contentContainer = CreateContentContainer();
				GroupedControls.AddContainer(contentContainer);
			}

		}

		/// <summary>
		/// Creates the control object to which the user can programmatically add child controls for <see cref="Content"/>.
		/// </summary>
		/// <returns>The <see cref="GroupControlContainer"/> to group the child controls.</returns>
		protected virtual GroupControlContainer CreateContentContainer() {
			return new GroupControlContainer(this);
		}

		#endregion


		#region Methods: Rendring hooks

		/// <summary>
		/// Raises the <see cref="Control.Init"/> event.
		/// </summary>
		/// <param name="e">The <see cref="EventArgs"/> object that contains the event data.</param>
		protected override void OnInit(EventArgs e) {
			base.OnInit(e);

			if(Content != null) Content.InstantiateIn(ContentContainer);

		}

		#endregion


		#region Explicit Implementation: IGroupContained

		GroupControlContainer IGroupContainedControl.Container {
			get { return Container; }
			set { Container = value; }
		}

		#endregion


	}

}